/*!
* @file BoundBox2D.h
* @brief 二维包围盒
* @date 2024/9/13
*/

#include <algorithm>
#include "BoundBox2D.h"

using namespace data;

template<class float_type>
bool BoundBox2<float_type>::operator==(const BoundBox2<float_type>& bbox) const
{
    // clang-format off
    return (_minX == bbox._minX) && (_minY == bbox._minY)
        && (_maxX == bbox._maxX) && (_maxX == bbox._maxY);
    // clang-format on
}

template<class float_type>
void BoundBox2<float_type>::MakeEmpty()
{
    _minX = _minY = traits_type::max();
    _maxX = _maxY = -traits_type::max();
}

template<class float_type>
bool BoundBox2<float_type>::IsValid() const
{
    return (_maxX >= _minX) && (_maxY >= _minY);
}

template<class float_type>
float_type BoundBox2<float_type>::Width() const
{
    return _maxX - _minX;
}

template<class float_type>
float_type BoundBox2<float_type>::Height() const
{
    return _maxY - _minY;
}

template<class float_type>
Vector2<float_type> BoundBox2<float_type>::Minimum() const
{
    return { _minX, _minY };
}

template<class float_type>
Vector2<float_type> BoundBox2<float_type>::Maximum() const
{
    return { _maxX, _maxY };
}

template<class float_type>
Vector2<float_type> BoundBox2<float_type>::Center() const
{
    return { (_minX + _maxX) * static_cast<float_type>(0.5), (_minY + _maxY) * static_cast<float_type>(0.5) };
}

template<class float_type>
void BoundBox2<float_type>::Add(const vector_type& v)
{
    _minX = std::min(_minX, v.x);
    _minY = std::min(_minY, v.y);
    _maxX = std::max(_maxX, v.x);
    _maxY = std::max(_maxY, v.y);
}

template<class float_type>
bool BoundBox2<float_type>::Contains(const vector_type& v) const
{
    return v.x >= _minX && v.x <= _maxX && v.y >= _minY && v.y <= _maxY;
}

template<class float_type>
bool BoundBox2<float_type>::Contains(const vector_type& v, float_type tol) const
{
    return v.x >= _minX - tol && v.x <= _maxX + tol && v.y >= _minY - tol
        && v.y <= _maxY + tol;
}

template<class float_type>
void BoundBox2<float_type>::Add(const BoundBox2<float_type>& bbox)
{
    _minX = std::min(_minX, bbox._minX);
    _maxX = std::max(_maxX, bbox._maxX);
    _minY = std::min(_minY, bbox._minY);
    _maxY = std::max(_maxY, bbox._maxY);
}

template<class float_type>
bool BoundBox2<float_type>::Intersect(const  BoundBox2<float_type>& bbox) const
{
    return (_minX < bbox._maxX && bbox._minX < _maxX && _minY < bbox._maxY && bbox._minY < _maxY);
}

template<class float_type>
bool BoundBox2<float_type>::IsEqual(const BoundBox2<float_type>& bbox, float_type tol) const
{
    return vector_type(_minX, _minY).IsEqual(vector_type(bbox._minX, bbox._minY), tol)
        && vector_type(_maxX, _maxY).IsEqual(vector_type(bbox._maxX, bbox._maxY), tol);
}

//导出
namespace Base
{
    template class DATA_API BoundBox2<float>;
    template class DATA_API BoundBox2<double>;
}